home *** CD-ROM | disk | FTP | other *** search
- /* ASCII Transfer External for Hermes © 1990 By John Raymonds.
-
- Written in THINK C 4.0.1 as an example external for Hermes protocol
- developers. Use of any code shown below in any program other than
- an external to be used with Hermes requires written permission from
- the author:
-
- John Raymonds
- 76174,205 (Compuserve)
- D3885 (AppleLink)
-
- Comments and suggestions are welcome.
-
- 040590 JR - Fixed Send.c (added startTime, bytesDone reset,
- and bytesTotal set)
-
- 050190 JR - Changed read.c and write.c to support new Hermes.h
- information. Added ++prp->filesDone in Receive.c
- so Hermes knows it was a good upload.
-
- 052290 JR - Changed over to the new Protocol Mover interface.
-
- 052990 JR - See the version history in the About notes for
- changes.
-
- */
-
- #include "Protocol.h"
- #include "ASCII.h"
-
- #include <:Mac #includes:SetUpA4.h>
-
- ProtoRecPtr PRP;
- ProtoGloPtr PGP;
-
-
- pascal OsErr main(message, prp, refCon)
- register int message;
- register ProtoRecPtr prp;
- long refCon;
- {
- register OsErr err;
- register ProtoGloPtr pgp;
- int doProtocol();
- RememberA0();
- SetUpA4();
- PRP = prp;
- err = noErr;
- if (!prp->protoData) {
- /* set up external globals if they do not exist */
- prp->protoData = NewHandle((long) sizeof(ProtoGloRec));
- err = MemError();
- if (!err) {
- /* let's lock the globals down and keep them locked until
- we exit the external.
- */
- MoveHHi(prp->protoData);
- HLock(prp->protoData);
- /* set up a global pointer to the globals we just allocated */
- PGP = *((ProtoGloHand) prp->protoData);
- /* make it a register variable since we will use it a
- number of times...
- */
- pgp = PGP;
- ClearBlock(pgp, (long) sizeof(ProtoGloRec));
- /* make a zero length handle for the StackSaver */
- pgp->SSR.stackData = NewHandle(0L);
- err = MemError();
- if (err) {
- HUnlock(prp->protoData);
- DisposHandle(prp->protoData);
- prp->protoData = 0L;
- }
- else {
- /* initialize our globals... */
- pgp->MIOPin.ioRefNum = prp->mRefIn;
- pgp->MIOPout.ioRefNum = prp->mRefOut;
- RWPrefs(FALSE);
- }
- }
- }
- else {
- /* set up a global pointer to the globals we allocated before */
- PGP = *((ProtoGloHand) prp->protoData);
- pgp = PGP;
- }
- if (!err) {
- /* use the StackSaver JumpBack routine to enter our code...
-
- On the first call (handle size of pgp->SSR = 0) JumpBack
- will simply call doProtocol which is defined elsewhere.
-
- On calls generated after a Return was executed JumpBack
- will restore the stack to the state it was in during the
- call the Return and being execution there.
- */
- err = JumpBack(message, prp, refCon, &pgp->SSR, doProtocol);
- if (err) {
- /* external has returned with a non-zero result. We are
- done so dispose of all of our stuff.
- */
- if (prp->protoData) {
- if (pgp->SSR.stackData) {
- DisposHandle(pgp->SSR.stackData);
- }
- HUnlock(prp->protoData);
- DisposHandle(prp->protoData);
- prp->protoData = 0L;
- }
- }
- }
- RestoreA4();
- return(err);
- }
-
- /* This is the routine pasted to JumpBack. Notice that the arguments
- are the same as those defined for the external itself. As note that
- all functions (unlike the external itself) use 'C' calling conventions.
- */
-
- int doProtocol(message, prp, refCon)
- int message;
- ProtoRecPtr prp;
- long refCon;
- {
- register OsErr err;
- err = noErr;
- switch(message) {
- case SEND:
- err = SendASCII();
- break;
- case RECEIVE:
- err = RecvASCII();
- break;
- case SETPREFS:
- doSetPrefs();
- default:
- err = 128;
- break;
- }
- /* make sure our async send buffers are written out */
- FlushWrite();
- return(err);
- }
-
- tellerror(errornum)
- int errornum;
- {
- /* set the errReason */
- SetError(errornum);
- /* immediately return to Hermes to show error: timeOut = 0 */
- Return(0, &PGP->SSR);
- }
-
- SetError(errornum)
- register int errornum;
- {
- register int i;
- register StringPtr eText;
- register ProtoRecPtr prp;
- Str255 errText, nText;
- prp = PRP;
- ++PGP->errCount;
- switch(errornum) {
- case TIMEOUT:
- eText = (StringPtr) "\pTimeout";
- break;
- case TOOMANYERR:
- eText = (StringPtr) "\pToo many errors";
- break;
- case NOTTEXT:
- eText = (StringPtr) "\pFile was not 'TEXT'";
- break;
- case NOCONTINUE:
- eText = (StringPtr) "\pPause not continued";
- break;
- default:
- eText = (StringPtr) "\pMac OS Error";
- break;
- }
- /* dispose of any error string that might already be there for some
- reason.
- */
- if (prp->errReason) {
- DisposHandle(prp->errReason);
- }
- /* show the error list */
- errText[0] = 0;
- for (i = 0; i<3; i++) {
- if (!PGP->errList[i]) {
- break;
- }
- NumToString((long) PGP->errList[i], nText);
- Pstrcat(errText, nText);
- Pstrcad(errText, ',');
- }
- /* tack on the current error */
- NumToString((long) errornum, nText);
- Pstrcat(errText, nText);
- Pstrcat(errText, "\p = ");
- Pstrcat(errText, eText);
- Pstrcat(errText, "\p (");
- NumToString((long) PGP->errCount, nText);
- Pstrcat(errText, nText);
- Pstrcat(errText, "\p errors)");
- prp->errReason = NewString(errText);
- prp->F.B.newError = TRUE;
- /* rotate error list */
- PGP->errList[2] = PGP->errList[1];
- PGP->errList[1] = PGP->errList[0];
- /* add current error to the list */
- PGP->errList[0] = errornum;
- /* This routine uses a lot of stack space so we are not going to
- do a Return here.
- */
- }
-
- ClearBlock(aPtr, size)
- register Ptr aPtr;
- register long size;
- {
- asm {
- tst.l size
- beq.s @theEnd
- btst.l #0, size
- beq.s @even
- ;
- ; size is odd so we must clear by byte
- ;
- @loop1 clr.b (aPtr)+
- subq.l #1, size
- bne.s @loop1
- bra.s @theEnd
- @even btst.l #1, size
- beq.s @loop3
- ;
- ; size is not a multiple of 4 so we must clear by word
- ;
- @loop2 clr.w (aPtr)+
- subq.l #2, size
- bne.s @loop2
- bra.s @theEnd
- ;
- ; size is a multiple of 4 so we can clear by long
- ;
- @loop3 clr.l (aPtr)+
- subq.l #4, size
- bne.s @loop3
- @theEnd
- }
- }
-
- Pstrcpy(s, t)
- register StringPtr s, t;
- {
- register int i;
- asm {
- clr.w i
- move.b (t), i
- @loop move.b (t)+, (s)+
- dbf i, @loop
- }
- }
-
- Pstrcat(s, t)
- register StringPtr s, t;
- {
- register int i;
- asm {
- move.l s, a0
- clr.w i
- move.b (s)+, i
- adda.w i, s
- move.b (t)+, i
- beq.s @theEnd
- add.b i, (a0)
- subq.w #1, i
- @loop move.b (t)+, (s)+
- dbf i, @loop
- @theEnd
- }
- }
-
- Pstrcad(s, c)
- register StringPtr s;
- register char c;
- {
- register int i;
- asm {
- addq.b #1, (s)
- clr.w i
- move.b (s), i
- adda.w i, s
- move.b c, (s)
- }
- }
-
- CenterWindow(wp, h, v)
- register WindowPtr wp;
- register int h, v;
- {
- Rect wRect;
- Rect ScrnRect;
- int top, left;
- GrafPtr savePort;
- register int dx, dy;
- ScrnRect = *((Rect *) (*((Handle) CurrentA5)-116));
- ScrnRect.top += MBarHeight;
- GetPort(&savePort);
- SetPort(wp);
- wRect = wp->portRect;
- LocalToGlobal(&topLeft(wRect));
- LocalToGlobal(&botRight(wRect));
- top = wRect.top;
- left = wRect.left;
- SetPort(savePort);
- CenterRect(&wRect, &ScrnRect);
- dx = wRect.left-ScrnRect.left;
- dy = wRect.top-ScrnRect.top;
- if ((h > 1) && dx) {
- dx = dx*h/100;
- }
- if ((v > 1) && dy) {
- dy = dy*h/100;
- }
- if (h) {
- h = ScrnRect.left+dx;
- }
- else {
- h = left;
- }
- if (v) {
- v = ScrnRect.top+dy;
- }
- else {
- v = top;
- }
- MoveWindow(wp, h, v, FALSE);
- }
-
- CenterRect(RtoCent, r)
- register Rect *RtoCent, *r;
- {
- int dx = MidPoint(r->left, r->right);
- int dy = MidPoint(r->top, r->bottom);
- dx -= MidPoint(RtoCent->left, RtoCent->right);
- dy -= MidPoint(RtoCent->top, RtoCent->bottom);
- OffsetRect(RtoCent, dx, dy);
- }
-
- int MidPoint(a, b)
- register int a, b;
- {
- return((a+b)/2);
- }
-